
import java.io.File;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import sk.upjs.gursky.bplustree.BPTree;

public class Generator {
	
	public static void main(String[] args) throws Exception {
	
		vygenerujSubor(500, "clovek.tab");		
		
		List<Zaznam> zaznamy = new ArrayList<Zaznam>();
		
		RandomAccessFile raf = new RandomAccessFile("clovek.tab", "r");
		
		FileChannel channel = raf.getChannel();
		
		ByteBuffer byteBuffer = ByteBuffer.allocate(4096);
		
		long length = raf.length();		
		long numberOfpages = length / 4096;		
		
		for (int i = 0; i < numberOfpages; i++) {
			byteBuffer.rewind();			
			channel.read(byteBuffer);
			byteBuffer.rewind();	//ak chceme nechat nezmenene
			int numberOfRecords = byteBuffer.getInt();
			for (int j = 0; j < numberOfRecords; j++) {
				Zaznam zaznam = new Zaznam();
				zaznam.load(byteBuffer);
//				System.out.println(zaznam);
				zaznamy.add(zaznam);
			}
		}
		channel.close();
		raf.close();
		
		BPTree<Kluc, Zaznam> tree =  new BPTree<Kluc, Zaznam>(Zaznam.class, new File("indexBP.idx"));
		tree.openNewFile();
		
		long time = System.currentTimeMillis();		
		
		for (Zaznam zaznam : zaznamy) {
			tree.add(zaznam);
		}
		
		time = System.currentTimeMillis() - time;
		System.out.println(time);
		
		tree.close();
		
		BPTree<Kluc, Zaznam> tree2 =  new BPTree<Kluc, Zaznam>(Zaznam.class, new File("indexBP2.idx"));
		
		time = System.currentTimeMillis();		
		
		Collections.sort(zaznamy);
		tree2.openAndBatchUpdate(zaznamy.iterator(), zaznamy.size());
		
		time = System.currentTimeMillis() - time;
		System.out.println(time);
		
		List<Zaznam> vysledok = tree2.rozsahovyDopyt(new Kluc("a"), new Kluc("b999999999"));
		
		for (Zaznam zaznam : vysledok) {
			System.out.println(zaznam);
		}
		
		tree2.close();
		
//		KlastrovanyBPTree bptree = new KlastrovanyBPTree(new File("clovek.tab"), new File("clovek.kl"));
//		NeklastrovanyBPTree bptree = new NeklastrovanyBPTree(new File("clovek.tab"), new File("clovek.kl"));
		
//		long time = System.currentTimeMillis();
//		ArrayList<Zaznam> vysledok = bptree.rozsahovyDopyt(new Kluc("a"), new Kluc("b999999999"));
//		time = System.currentTimeMillis() - time;
		
//		System.out.println(time);
	}
	

	
	/**
	 * Vytvori subor so zadanym menom/umiestnenim a poctom stranok velkosti 4096B naplnenych nahodnymi datami.
	 * Na jednu stranku sa vojde 85 zaznamov, menej zaznamov (ale nahodne) bude vzdy obsahovat posledna stranka.
	 * Sobor obsahuje zaznamy pre tabulku podla tejto definicie
	 * 
	 * create table clovek (
	 * 		meno char(10),
	 *  	priezvisko char(10),
	 *  	vek int,
	 *  	plat int
	 * )
	 * 
	 * Jeden zaznam ma teda 48B a v subore su vramci kazdej stranky radene bezprostredne za sebou s tym, 
	 * ze kazda stranka ma na prvych styroch bytoch pocet zaznamov, ktore obsahuje. Stranky su tiez radene 
	 * bezprostredne za sebou.
	 * 
	 * @param pocetStranok - kolko stranok naplnenych nahodnymi datami sa ma vytvorit
	 * @param subor - meno alebo cela cesta s menom suboru, ktory sa ma vytvorit
	 * @throws Exception
	 */
	public static void vygenerujSubor(int pocetStranok, String subor) throws Exception {
		
		Random r = new Random();
		File   f = new File(subor);
		
		if (!f.exists()) {
			f.createNewFile();
		}
		RandomAccessFile raf = new RandomAccessFile(f, "rw");
		
		FileChannel channel = raf.getChannel();
		ByteBuffer  buffer = ByteBuffer.allocateDirect(4096);
		
		for (int i = 0; i < pocetStranok; i++) {
			int z = 85;
			if (i == pocetStranok - 1) {
				z = (int) (Math.random() * 84 + 1);
			}
			buffer.clear();
			buffer.putInt(z);
			for (int j = 0; j < z; j++) {
				String str = Long.toString(Math.abs(r.nextLong()), 36);
				
				for (int k = 0; k < 10; k++) {
					try {
						buffer.putChar(str.charAt(k));
					} catch (StringIndexOutOfBoundsException e) {
						buffer.putChar(' ');
					}
				}
				str = Long.toString(Math.abs(r.nextLong()), 36);
				for (int k = 0; k < 10; k++) {
					try {
						buffer.putChar(str.charAt(k));
					} catch (StringIndexOutOfBoundsException e) {
						buffer.putChar(' ');
					}
				}
				buffer.putInt((int) (Math.random() * 50 + 18));
				buffer.putInt((int) (Math.random() * 2000 + 300));
			}
			buffer.rewind();
			channel.write(buffer, i * 4096);
		}
		
		channel.close();
		raf.close();
	}
}